#! /usr/bin/env python
#coding=utf-8

import os
import sys

sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../"))

from utils import ResterHelper
from utils import ResterStringBuilder

class MemRecordEntry(ResterStringBuilder):
	@staticmethod
	def getFields():
		return ("id", "name", "processes", "threads", "region_types", "vmmap_regions", "rss", "description", "Pages_free", "Pages_active", "Pages_inactive", "Pages_speculative", "Pages_throttled", "Pages_wired_down", "Pages_purgeable", "Translation_faults", "Pages_copy_on_write", "Pages_zero_filled", "Pages_reactivated", "Pages_purged", "File_backed_pages", "Anonymous_pages", "Pages_stored_in_compressor", "Pages_occupied_by_compressor", "Decompressions", "Compressions", "Pageins", "Pageouts", "Swapins", "Swapouts") + ("vmmap_vsize", "vmmap_resident", "vmmap_dirty", "vmmap_swap") + ("footprint_Dirty", "footprint_Clean", "footprint_Reclaimable", "footprint_Regions")

class ProcessEntry(ResterStringBuilder):
	# Override to limit value length for command
	def value_fixer(self, key, val, xargs):
		if not xargs:
			return val
		if xargs and "format" in xargs:
			return val
		if key == "command" and len(val) > 32:
			return val[-32:]
		return val

	@staticmethod
	def getFields():
		return ("id", "record_id", "record_name", "pid", "ppid", "command", "threads", "rss", "vsize", "region_types") + ("vmmap_regions", "vmmap_vsize", "vmmap_resident", "vmmap_dirty", "vmmap_swap") + ("footprint_Dirty", "footprint_Clean", "footprint_Reclaimable", "footprint_Regions") + ("cpu", "state", "priority", "nice", "wq")

class RegionTypeEntry(ResterStringBuilder):
	@staticmethod
	def getFields():
		return ("id", "record_id", "processes", "record_name", "name", "vmmap_regions") + ("vsize", "resident", "dirty", "swap")

class RegionDetailEntry(ResterStringBuilder):
	@staticmethod
	def getFields():
		return ("id", "record_id", "process_id", "record_name", "command", "type", "addr", "ugo", "sharemode", "purge", "detail") + ("vsize", "resident", "dirty", "swap")

class MemRecordsRestMgr(object):
	def __init__(self, product):
		self._product = product

	def get_all(self, xargs=None):
		sqlcmd = "select * from mem_records"
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		records = []
		for row in cursor:
			records.append(MemRecordEntry(row, cursor))
		return records

	def doRestRequest(self, id, mod, args):
		mCmdMap = {
			'processes':self.__dbGetProcesses,
			'regiontypes':self.__dbGetMemoryRegionTypes,
			'processes_by_name': self.__dbGetProcessesByName,
			'processes_by_type': self.__dbGetProcessesByName,
			'processes_by_type_name': self.__dbGetProcessesByTypeName,
			'regions_by_type': self.__dbGetRegionsByType,
			'regions_by_type_name': self.__dbGetRegionsByTypeName,
			'regions_by_process': self.__dbGetRegionsByProcess,
			'regiontypes_by_process': self.__dbGetRegionTypesByProcess,
			'regiontypes_by_name': self.__dbGetRegionTypesByName
		}
		vals = mCmdMap[mod](id, args)
		return ResterHelper.build_array_content(vals, args)

	def __dbGetProcesses(self, id, args):
		sqlcmd = "select * from processes_details where record_id=%d" % int(id)
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		processes = []
		for row in cursor:
			processes.append(ProcessEntry(row, cursor))
		return processes

	def __dbGetMemoryRegionTypes(self, id, args):
		sqlcmd = "select name, record_name, count(DISTINCT process_id) as processes, sum(regions) as vmmap_regions, sum(vsize) as vsize, sum(resident) as resident, sum(dirty) as dirty, sum(swap) as swap from region_types_details where record_id=%d GROUP by name" % int(id)
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		regionTypes = []
		for row in cursor:
			regionTypes.append(RegionTypeEntry(row, cursor))
		return regionTypes

	def __dbGetProcessesByName(self, id, args):
		cursor = self._product.getCursor()

		sqlcmd = "select command from processes where id=%d" % int(id)
		cursor.execute(sqlcmd)
		command = ""
		for row in cursor:
			command = row[0]
			break

		sqlcmd = 'select * from processes_details where command="%s"' % command
		cursor.execute(sqlcmd)

		processes = []
		for row in cursor:
			processes.append(ProcessEntry(row, cursor))
		return processes

	def __dbGetProcessesByTypeName(self, id, args):
		cursor = self._product.getCursor()

		sqlcmd = 'select * from processes_details where id in (select process_id from region_types where record_id=%s and name="%s")' % (id, args["region_type"])
		cursor.execute(sqlcmd)

		processes = []
		for row in cursor:
			processes.append(ProcessEntry(row, cursor))
		return processes

	def __dbGetProcessesByType(self, id, args):
		cursor = self._product.getCursor()

		sqlcmd = 'select * from processes_details where type="%s"' % command
		cursor.execute(sqlcmd)

		processes = []
		for row in cursor:
			processes.append(ProcessEntry(row, cursor))
		return processes

	def __dbGetRegionsByType(self, id, args):
		cursor = self._product.getCursor()

		sqlcmd = 'select * from regions_details where type_id=%d' % int(id)
		cursor.execute(sqlcmd)

		regions = []
		for row in cursor:
			regions.append(RegionDetailEntry(row, cursor))
		return regions

	def __dbGetRegionsByTypeName(self, id, args):
		cursor = self._product.getCursor()

		sqlcmd = 'select * from regions_details where record_id=%s and type="%s"' % (id, args["name"])
		print(sqlcmd)
		cursor.execute(sqlcmd)

		regions = []
		for row in cursor:
			regions.append(RegionDetailEntry(row, cursor))
		return regions

	def __dbGetRegionsByProcess(self, id, args):
		cursor = self._product.getCursor()

		sqlcmd = 'select * from regions_details where process_id=%d' % int(id)
		cursor.execute(sqlcmd)

		regions = []
		for row in cursor:
			regions.append(RegionDetailEntry(row, cursor))
		return regions

	def __dbGetRegionTypesByProcess(self, id, args):
		sqlcmd = "select id, name, regions as vmmap_regions, vsize, resident, dirty, swap from region_types where process_id=%d" % int(id)
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		regionTypes = []
		for row in cursor:
			regionTypes.append(RegionTypeEntry(row, cursor))
		return regionTypes

	def __dbGetRegionTypesByName(self, id, args):
		sqlcmd = "select record_id, record_name, name, count(process_id) as processes, sum(regions) as vmmap_regions, sum(vsize) as vsize, sum(resident) as resident, sum(dirty) as dirty, sum(swap) as swap from region_types_details where name='%s' GROUP BY record_id" % id
		cursor = self._product.getCursor()
		cursor.execute(sqlcmd)

		regionTypes = []
		for row in cursor:
			regionTypes.append(RegionTypeEntry(row, cursor))
		return regionTypes

if __name__ == "__main__":
	import products

	product_mgr = products.Products()
	prod = product_mgr.get_product_by_name("openharmony", "rk3568")
	prod.load_db()

	mgr = MemRecordsRestMgr(prod)

	print(mgr.doRestRequest(1, "records", {}))

